﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
namespace System {
    public enum JudgeType {
        数字,
        英文和数字,
        英文数字下划线,
        中文英文数字下划线,
        手机号码,
        电话号码,
        身份证号码,
        年月日,
        IP,
        URL,
        邮件,
    }

    public static partial class Extention {
        #region Split
        public static string[] Split(this string str,string separator) {
            return str.Split(new[] { separator },StringSplitOptions.None);
        }
        public static string[] Split(this string str,string separator,StringSplitOptions options) {
            return str.Split(new[] { separator },options);
        }
        public static string[] SplitToLines(this string str) {
            return str.Split(Environment.NewLine);
        }
        public static string[] SplitToLines(this string str,StringSplitOptions options) {
            return str.Split(Environment.NewLine,options);
        }
        #endregion
        #region Regex
        public static bool IsMatch(this string s,string pattern) {
            if(s==null) return false;
            else return Regex.IsMatch(s,pattern);
        }
        public static string Match(this string s,string pattern) {
            if(s==null) return "";
            return Regex.Match(s,pattern).Value;
        }
        public static bool IsMatch(this string s,JudgeType pattern) {
            bool flg = false;
            switch(pattern) {
                case JudgeType.数字:
                    flg=s.IsMatch(@"^[0-9]+$");
                    break;
                case JudgeType.英文和数字:
                    flg=s.IsMatch(@"^[A-Za-z0-9]+$");
                    break;
                case JudgeType.英文数字下划线:
                    flg=s.IsMatch(@"^[A-Za-z0-9_]+$");
                    break;
                case JudgeType.中文英文数字下划线:
                    flg=s.IsMatch(@"^[\u4E00-\u9FA5A-Za-z0-9_]+$");
                    break;
                case JudgeType.手机号码:
                    flg=s.IsMatch(@"^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$");
                    break;
                case JudgeType.电话号码://("XXX-XXXXXXX"、"XXXX-XXXXXXXX"、"XXX-XXXXXXX"、"XXX-XXXXXXXX"、"XXXXXXX"和"XXXXXXXX)
                    flg=s.IsMatch(@"^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$");
                    break;
                case JudgeType.身份证号码:
                    flg=s.IsMatch(@"^\d{15}|\d{18}$");
                    break;
                case JudgeType.年月日://2022-01-07
                    flg=s.IsMatch(@"^\d{4}-\d{1,2}-\d{1,2}");
                    break;
                case JudgeType.IP://127.0.0.1
                    flg=s.IsMatch(@"^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$");
                    break;
                case JudgeType.邮件://2022-01-07
                    flg=s.IsMatch(@"^[a-z]([a-z0-9]*[-_]?[a-z0-9]+)*@([a-z0-9]*[-_]?[a-z0-9]+)+[\.][a-z]{2,3}([\.][a-z]{2})?$");
                    break;
                case JudgeType.URL:
                    flg=s.IsMatch(@"(http[s]?|ftp):\/\/[^\/\.]+?\..+\w$");
                    break;
                default:
                    break;
            }

            return flg;
        }
        #endregion
        #region 类型转换
        public static bool IsInt(this string s) {
            int i;
            return int.TryParse(s,out i);
        }
        public static int ToInt(this string s) {
            try {
                return int.Parse(s);
            } catch {
                return 0;
            }
        }
        public static byte[] ToSHA1Bytes(this string str) {
            return str.ToSHA1Bytes(Encoding.UTF8);
        }

        public static byte[] ToSHA1Bytes(this string str,Encoding encoding) {
            SHA1 sha1 = new SHA1CryptoServiceProvider();
            byte[] inputBytes = encoding.GetBytes(str);
            byte[] outputBytes = sha1.ComputeHash(inputBytes);
            return outputBytes;
        }

        public static string ToSHA1String(this string str) {
            return str.ToSHA1String(Encoding.UTF8);
        }

        public static string ToSHA1String(this string str,Encoding encoding) {
            byte[] sha1Bytes = str.ToSHA1Bytes(encoding);
            string resStr = BitConverter.ToString(sha1Bytes);
            return resStr.Replace("-","").ToLower();
        }

        public static int ToInt_FromBinString(this string str) {
            return Convert.ToInt32(str,2);
        }

        public static int ToInt0X(this string str) {
            int num = Int32.Parse(str,NumberStyles.HexNumber);
            return num;
        }

        public static double ToDouble(this string str) {
            try {
                return Convert.ToDouble(str);
            } catch {
                return 0;
            }
        }

        public static byte[] ToBytes(this string str) {
            return Encoding.Default.GetBytes(str);
        }

        public static byte[] ToBytes(this string str,Encoding theEncoding) {
            return theEncoding.GetBytes(str);
        }

        public static byte[] To0XBytes(this string str) {
            List<byte> resBytes = new List<byte>();
            for(int i = 0;i<str.Length;i=i+2) {
                string numStr = $@"{str[i]}{str[i+1]}";
                resBytes.Add((byte)numStr.ToInt0X());
            }
            return resBytes.ToArray();
        }

        public static byte[] ToASCIIBytes(this string str) {
            return str.ToList().Select(x => (byte)x).ToArray();
        }

        public static DateTime? ToDateTime(this string str) {
            try {
                return Convert.ToDateTime(str);
            } catch(Exception) {
                return null;
            }
        }
        public static string ToFirstUpperStr(this string str) {
            return str.Substring(0,1).ToUpper()+str.Substring(1);
        }

        public static string ToFirstLowerStr(this string str) {
            return str.Substring(0,1).ToLower()+str.Substring(1);
        }

        public static IPEndPoint ToIPEndPoint(this string str) {
            IPEndPoint iPEndPoint = null;
            try {
                string[] strArray = str.Split(':').ToArray();
                string addr = strArray[0];
                int port = Convert.ToInt32(strArray[1]);
                iPEndPoint=new IPEndPoint(IPAddress.Parse(addr),port);
            } catch {
                iPEndPoint=null;
            }
            return iPEndPoint;
        }
        #endregion
        #region Base64
        public static byte[] ToBytes_FromBase64Str(this string base64Str) {
            return Convert.FromBase64String(base64Str);
        }
        public static string Base64Encode(this string source) {
            return Base64Encode(source,Encoding.UTF8);
        }

        public static string Base64Encode(this string source,Encoding encoding) {
            string encode = string.Empty;
            byte[] bytes = encoding.GetBytes(source);
            try {
                encode=Convert.ToBase64String(bytes);
            } catch {
                encode=source;
            }
            return encode;
        }

        public static string Base64Decode(this string result) {
            return Base64Decode(result,Encoding.UTF8);
        }

        public static string Base64Decode(this string result,Encoding encoding) {
            string decode = string.Empty;
            byte[] bytes = Convert.FromBase64String(result);
            try {
                decode=encoding.GetString(bytes);
            } catch {
                decode=result;
            }
            return decode;
        }
        #endregion
        #region File
        public static bool CreateDir(this string name) {
            if(!Directory.Exists(name)) {
                Directory.CreateDirectory(name);
            }
            return true;
        }
        public static void WriteText(this string path,string contents) {
            File.WriteAllText(path,contents);
        }
        public static void DeleteFile(this string path) {
            if(File.Exists(path)) File.Delete(path);
        }

        public static bool FileExists(this string filename) {
            return System.IO.File.Exists(filename);
        }
        #endregion
        public static string ToMD5String(this string str) {
            MD5 md5 = MD5.Create();
            byte[] inputBytes = Encoding.UTF8.GetBytes(str);
            byte[] hashBytes = md5.ComputeHash(inputBytes);
            StringBuilder sb = new StringBuilder();
            for(int i = 0;i<hashBytes.Length;i++) {
                sb.Append(hashBytes[i].ToString("x2"));
            }
            return sb.ToString();
        }


        public static void OpenProcess(this string s) {
            Process.Start(s);
        }
        public static string ExecuteDOS(this string cmd,out string error) {
            Process process = new Process();
            process.StartInfo.FileName="cmd.exe";
            process.StartInfo.UseShellExecute=false;
            process.StartInfo.RedirectStandardInput=true;
            process.StartInfo.RedirectStandardOutput=true;
            process.StartInfo.RedirectStandardError=true;
            process.StartInfo.CreateNoWindow=true;
            process.Start();
            process.StandardInput.WriteLine(cmd);
            process.StandardInput.WriteLine("exit");
            error=process.StandardError.ReadToEnd();
            return process.StandardOutput.ReadToEnd();
        }
        public static string ToSBC(this string input) {
            char[] c = input.ToCharArray();
            for(int i = 0;i<c.Length;i++) {
                if(c[i]==32) {
                    c[i]=(char)12288;
                    continue;
                }
                if(c[i]<127)
                    c[i]=(char)(c[i]+65248);
            }
            return new string(c);
        }
        public static string ToDBC(this string input) {
            char[] c = input.ToCharArray();
            for(int i = 0;i<c.Length;i++) {
                if(c[i]==12288) {
                    c[i]=(char)32;
                    continue;
                }
                if(c[i]>65280&&c[i]<65375)
                    c[i]=(char)(c[i]-65248);
            }
            return new string(c);
        }
        public static string Reverse(this string value) {
            char[] input = value.ToCharArray();
            char[] output = new char[value.Length];
            for(int i = 0;i<input.Length;i++)
                output[input.Length-1-i]=input[i];
            return new string(output);
        }
        #region 删除最后一个字符之后的字符
        public static string DelLastComma(this string str) {
            return str.Substring(0,str.LastIndexOf(","));
        }
        public static string DelLastChar(this string str,string strchar) {
            return str.Substring(0,str.LastIndexOf(strchar));
        }
        public static string DelLastLength(this string str,int Length) {
            if(string.IsNullOrEmpty(str))
                return "";
            str=str.Substring(0,str.Length-Length);
            return str;
        }
        /// <summary>
        /// 删除/* */ <!-- --> // --注释和空行
        /// </summary>
        public static string DelNote(this string instr) {
            string m_outstr = instr.Clone() as string;
            RegexOptions options = RegexOptions.Multiline|RegexOptions.IgnoreCase;
            //删除 /* */ 注释
            //m_outstr = new Regex(@"\/\/[^\n]*|\/\*([^\*^\/]*|[\*^\/*]*|[^\**\/]*)*\*+\/",options).Replace(m_outstr,string.Empty);
            m_outstr=new Regex(@"/\*{1,2}[\s\S]*?\*/",options).Replace(m_outstr,string.Empty);
            //删除<!-- --> 注释：
            m_outstr=new Regex(@"<!-[\s\S]*?-->",options).Replace(m_outstr,string.Empty);
            //删除 // 注释 ://也删除了
            m_outstr=new Regex(@"[^:]//{1,2}[\s\S]*?\n",options).Replace(m_outstr,string.Empty);
            //删除 -- SQL注释
            // m_outstr = new Regex(@"[\t]*--[^>][^\n]*\n",options).Replace(m_outstr,string.Empty);
            //删除空白行
            //m_outstr = new Regex(@"^\s*\n",options).Replace(m_outstr,string.Empty);
            return m_outstr;
        }
        #endregion 删除最后一个字符之后的字符
        public static string If(this string str,bool condition) {
            return condition ? str : string.Empty;
        }
        public static bool EqualsIgnoreCase(this string s,string value) {
            return s.Equals(value,StringComparison.OrdinalIgnoreCase);
        }
        public static string FirstCharToLower(this string s) {
            if(string.IsNullOrEmpty(s))
                return s;
            string str = s.First().ToString().ToLower()+s.Substring(1);
            return str;
        }
        public static string FirstCharToUpper(this string s) {
            if(string.IsNullOrEmpty(s))
                return s;
            string str = s.First().ToString().ToUpper()+s.Substring(1);
            return str;
        }
        public static string StringToSql(this string[] str,bool isInt) {
            if(isInt) {
                return string.Join(",",str);
            } else {
                StringBuilder idsStr = new StringBuilder();
                for(int i = 0;i<str.Length;i++) {
                    if(i>0) {
                        idsStr.Append(",");
                    }
                    idsStr.Append("'").Append(str[i]).Append("'");
                }
                return idsStr.ToString();
            }
        }
        /// <summary>
        /// 从脚本获取SQL命令
        /// </summary>
        public static IList<string> ToSqlCommands(this string sql) {
            var commands = new List<string>();
            sql=Regex.Replace(sql,@"\\\r?\n",string.Empty);
            var batches = Regex.Split(sql,@"^\s*(GO[ \t]+[0-9]+|GO)(?:\s+|$)",RegexOptions.IgnoreCase|RegexOptions.Multiline);
            for(var i = 0;i<batches.Length;i++) {
                if(string.IsNullOrEmpty(batches[i])||batches[i].StartsWith("GO",StringComparison.OrdinalIgnoreCase))
                    continue;
                var count = 1;
                if(i!=batches.Length-1&&batches[i+1].StartsWith("GO",StringComparison.OrdinalIgnoreCase)) {
                    var match = Regex.Match(batches[i+1],"([0-9]+)");
                    if(match.Success)
                        count=int.Parse(match.Value);
                }
                var builder = new StringBuilder();
                for(var j = 0;j<count;j++) {
                    builder.Append(batches[i]);
                    if(i==batches.Length-1)
                        builder.AppendLine();
                }
                commands.Add(builder.ToString());
            }
            return commands;
        }
        public static string Format(this string str,params object[] args) {
            return string.Format(str,args);
        }
        /// <summary>
        /// 向URL地址添加参数
        /// </summary>
        /// <param name="url"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string AddParamToUrl(this string url,string key,string value) {
            Regex reg = new Regex(@"^.*\?.+=.+$");
            if(reg.IsMatch(url)) {
                url+="&"+key+"="+value;
            } else {
                url+="?"+key+"="+value;
            }
            return url;
        }
        public static string CharAt(this string s,int index) {
            if((index>=s.Length)||(index<0))
                return "";
            return s.Substring(index,1);
        }
        /// <summary>
        /// 删除HTML文本中的脚本样式注释空行
        /// </summary>
        public static string DelHTML(this string instr) {
            string m_outstr = instr.Clone() as string;
            m_outstr=new Regex(@"(?m)<script[^>]*>(\w|\W)*?</script[^>]*>",RegexOptions.Multiline|RegexOptions.IgnoreCase).Replace(m_outstr,string.Empty);
            m_outstr=new Regex(@"(?m)<style[^>]*>(\w|\W)*?</style[^>]*>",RegexOptions.Multiline|RegexOptions.IgnoreCase).Replace(m_outstr,string.Empty);
            m_outstr=new Regex(@"(?m)<link[^>]*>(\w|\W)*?[^>]*>",RegexOptions.Multiline|RegexOptions.IgnoreCase).Replace(m_outstr,string.Empty);
            m_outstr=new Regex(@"<iframe[\s\S]+</iframe *>",RegexOptions.Multiline|RegexOptions.IgnoreCase).Replace(m_outstr,string.Empty);
            m_outstr=new Regex(@"<frameset[\s\S]+</frameset  *>",RegexOptions.Multiline|RegexOptions.IgnoreCase).Replace(m_outstr,string.Empty);
            m_outstr=new Regex(@"-->",RegexOptions.Multiline|RegexOptions.IgnoreCase).Replace(m_outstr,string.Empty);
            m_outstr=new Regex(@"<!--.*",RegexOptions.Multiline|RegexOptions.IgnoreCase).Replace(m_outstr,string.Empty);
            m_outstr=new Regex(@"(&nbsp;)+").Replace(m_outstr,"");
            m_outstr=new Regex(@"(\r\n\r\n)+").Replace(m_outstr,"");
            return m_outstr;
        }
        public static bool IsNullOrWhiteSpace(this string value) {
            if((object)value==null) {
                return true;
            }
            for(int i = 0;i<value.Length;i++) {
                if(!char.IsWhiteSpace(value[i])) {
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 过滤不可见字符
        /// </summary>
        /// <param name="sourceString">原始字符</param>
        /// <returns>删除后结果</returns>
        public static string DeleteControlChar(this string sourceString) {
            System.Text.StringBuilder sBuilder = new System.Text.StringBuilder();
            for(int i = 0;i<sourceString.Length;i++) {
                int Unicode = sourceString[i];
                if(Unicode>31&&Unicode!=127) {
                    sBuilder.Append(sourceString[i].ToString());
                }
            }
            return sBuilder.ToString();
        }
    }
}